home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DJINC106.ARJ / FIX.H < prev    next >
C/C++ Source or Header  |  1992-03-29  |  10KB  |  467 lines

  1. //
  2. // Fix.h : variable length fixed point data type 
  3. //
  4.  
  5. #ifndef _Fix_h
  6. #ifdef __GNUG__
  7. #pragma interface
  8. #endif
  9. #define _Fix_h 1
  10.  
  11. #include <stream.h>
  12. #include <std.h>
  13. #include <stddef.h>
  14. #include <Integer.h>
  15. #include <builtin.h>
  16.  
  17. typedef unsigned short uint16;
  18. typedef short int16;
  19. typedef unsigned long  uint32;
  20. typedef long int32;
  21.  
  22. #define _Fix_min_length     1
  23. #define _Fix_max_length        65535
  24.  
  25. #define _Fix_min_value        -1.0
  26. #define _Fix_max_value        1.0
  27.  
  28. extern uint16 Fix_default_length;
  29. extern int    Fix_default_print_width;
  30.  
  31. struct _Frep                    // internal Fix representation
  32. {
  33.   uint16 len;                  // length in bits
  34.   uint16 siz;            // allocated storage
  35.   int16 ref;                  // reference count
  36.   uint16 s[1];            // start of ushort array represention
  37. };
  38.  
  39. typedef struct _Frep* _Fix;
  40.  
  41. extern _Frep _Frep_0;
  42. extern _Frep _Frep_m1;
  43. extern _Frep _Frep_quotient_bump;
  44.  
  45. class Fix
  46. {
  47.   _Fix            rep;
  48.  
  49.           Fix(_Fix);
  50.  
  51.   void          unique();
  52.  
  53. public:
  54.           Fix();
  55.                   Fix(Fix&);
  56.           Fix(double&);
  57.                   Fix(int);
  58.                   Fix(int, Fix&);
  59.                   Fix(int, double&);
  60.                   Fix(int, _Frep*);
  61.  
  62.                   ~Fix();
  63.  
  64.   Fix             operator =  (Fix&);
  65.   Fix             operator =  (double&);
  66.  
  67.   friend int      operator == (Fix&, Fix& );
  68.   friend int      operator != (Fix&, Fix&);
  69.  
  70.   friend int      operator <  (Fix&, Fix&);
  71.   friend int      operator <= (Fix&, Fix&);
  72.   friend int      operator >  (Fix&, Fix&);
  73.   friend int      operator >= (Fix&, Fix&);
  74.  
  75.   Fix&            operator +  ();
  76.   Fix             operator -  ();
  77.  
  78.   friend Fix      operator +  (Fix&, Fix&);
  79.   friend Fix      operator -  (Fix&, Fix&);
  80.   friend Fix      operator *  (Fix&, Fix&);
  81.   friend Fix      operator /  (Fix&, Fix&);
  82.  
  83.   friend Fix      operator *  (Fix&, int);
  84.   friend Fix      operator *  (int, Fix&);
  85.   friend Fix      operator %  (Fix&, int);
  86.   friend Fix      operator << (Fix&, int);
  87.   friend Fix      operator >> (Fix&, int);
  88.  
  89. #ifdef __GNUG__
  90.   friend Fix     operator <? (Fix&, Fix&); // min
  91.   friend Fix     operator >? (Fix&, Fix&); // max
  92. #endif
  93.  
  94.   Fix            operator += (Fix&);
  95.   Fix            operator -= (Fix&);
  96.   Fix            operator *= (Fix&);
  97.   Fix            operator /= (Fix&);
  98.  
  99.   Fix            operator *= (int);
  100.   Fix            operator %= (int);
  101.   Fix            operator <<=(int);
  102.   Fix            operator >>=(int);
  103.  
  104.   friend char*    Ftoa(Fix&, int width = Fix_default_print_width);
  105.   friend Fix      atoF(const char*, int len = Fix_default_length);
  106.   
  107.   friend istream& operator >> (istream&, Fix&);
  108.   friend ostream& operator << (ostream&, Fix&);
  109.  
  110.   // built-in functions
  111.   friend Fix      abs(Fix);        // absolute value
  112.   friend int      sgn(Fix&);        // -1, 0, +1
  113.   friend Integer  mantissa(Fix&);    // integer representation
  114.   friend double   value(Fix&);        // double value
  115.   friend int      length(Fix&);        // field length
  116.   friend void      show(Fix&);        // show contents
  117.  
  118.   // error handlers
  119.   void            error(const char* msg);        // error handler
  120.   void            range_error(const char* msg);    // range error handler
  121.  
  122.   // internal class functions
  123.   friend void      mask(_Fix);
  124.   friend int      compare(_Fix, _Fix = &_Frep_0);
  125.  
  126.   friend _Fix      new_Fix(uint16);
  127.   friend _Fix      new_Fix(uint16, _Fix);
  128.   friend _Fix      new_Fix(uint16, double);
  129.  
  130.   friend _Fix      copy(_Fix, _Fix);
  131.   friend _Fix      negate(_Fix, _Fix = NULL);
  132.   friend _Fix      add(_Fix, _Fix, _Fix = NULL);
  133.   friend _Fix      subtract(_Fix, _Fix, _Fix = NULL);
  134.   friend _Fix      multiply(_Fix, _Fix, _Fix = NULL);
  135.   friend _Fix      multiply(_Fix, int, _Fix = NULL);
  136.   friend _Fix      divide(_Fix, _Fix, _Fix = NULL, _Fix = NULL);
  137.   friend _Fix      shift(_Fix, int, _Fix = NULL);
  138.  
  139.   // non-operator versions for user
  140.   friend void      negate(Fix& x, Fix& r);
  141.   friend void      add(Fix& x, Fix& y, Fix& r);
  142.   friend void      subtract(Fix& x, Fix& y, Fix& r);
  143.   friend void      multiply(Fix& x, Fix& y, Fix& r);
  144.   friend void      divide(Fix& x, Fix& y, Fix& q, Fix& r);
  145.   friend void      shift(Fix& x, int y, Fix& r);
  146. };
  147.  
  148. // error handlers
  149.  
  150. extern void    
  151.   default_Fix_error_handler(const char*),
  152.   default_Fix_range_error_handler(const char*);
  153.  
  154. extern one_arg_error_handler_t 
  155.   Fix_error_handler,
  156.   Fix_range_error_handler;
  157.  
  158. extern one_arg_error_handler_t 
  159.   set_Fix_error_handler(one_arg_error_handler_t f),
  160.   set_Fix_range_error_handler(one_arg_error_handler_t f);
  161.  
  162. typedef void (*Fix_peh)(_Fix&);
  163. extern Fix_peh Fix_overflow_handler;
  164.  
  165. extern void 
  166.   Fix_overflow_saturate(_Fix&),
  167.   Fix_overflow_wrap(_Fix&),
  168.   Fix_overflow_warning_saturate(_Fix&),
  169.   Fix_overflow_warning(_Fix&),
  170.   Fix_overflow_error(_Fix&);
  171.  
  172. extern Fix_peh set_overflow_handler(Fix_peh);
  173.  
  174. extern int Fix_set_default_length(int);
  175.  
  176. // function definitions
  177.  
  178.  
  179. inline void Fix::unique()
  180. {
  181.   if ( rep->ref > 1 )
  182.   {
  183.     rep->ref--;
  184.     rep = new_Fix(rep->len,rep);
  185.   }
  186. }
  187.  
  188. inline void mask (_Fix x)
  189. {
  190.   int n = x->len & 0x0f;
  191.   if ( n )
  192.     x->s[x->siz - 1] &= 0xffff0000 >> n; 
  193. }
  194.  
  195. inline _Fix copy(_Fix from, _Fix to)
  196. {
  197.   uint16 *ts = to->s, *fs = from->s;
  198.   int ilim = to->siz < from->siz ? to->siz : from->siz;
  199.   for ( int i=0; i < ilim; i++ )
  200.     *ts++ = *fs++;
  201.   for ( ; i < to->siz; i++ )
  202.     *ts++ = 0;
  203.   mask(to);
  204.   return to;
  205. }
  206.  
  207. inline Fix::Fix(_Fix f)
  208. {
  209.   rep = f;
  210. }
  211.  
  212. inline Fix::Fix()
  213. {
  214.   rep = new_Fix(Fix_default_length);
  215. }
  216.  
  217. inline Fix::Fix(int len)
  218. {
  219.   if ( len < _Fix_min_length || len > _Fix_max_length )
  220.     error("illegal length in declaration");
  221.   rep = new_Fix((uint16 )len);
  222. }
  223.  
  224. inline Fix::Fix(double& d)
  225. {
  226.   rep = new_Fix(Fix_default_length,d);
  227. }
  228.  
  229. inline Fix::Fix(Fix&  y)
  230. {
  231.   rep = y.rep; rep->ref++;
  232. }
  233.  
  234. inline Fix::Fix(int len, Fix&  y)
  235. {
  236.   if ( len < _Fix_min_length || len > _Fix_max_length )
  237.     error("illegal length in declaration");
  238.   rep = new_Fix((uint16 )len,y.rep);
  239. }
  240.  
  241. inline Fix::Fix(int len, _Frep* fr)
  242. {
  243.   if ( len <     1  || len >     65535  )
  244.     error("illegal length in declaration");
  245.   rep = new_Fix((uint16 )len,fr);
  246. }
  247.  
  248. inline Fix::Fix(int len, double& d)
  249. {
  250.   if ( len < _Fix_min_length || len > _Fix_max_length )
  251.     error("illegal length in declaration");
  252.   rep = new_Fix((uint16 )len,d);
  253. }
  254.  
  255. inline Fix::~Fix()
  256. {
  257.   if ( --rep->ref <= 0 ) delete rep;
  258. }
  259.  
  260. inline Fix  Fix::operator = (Fix&  y)
  261. {
  262.   if ( rep->len == y.rep->len ) {
  263.     ++y.rep->ref;
  264.     if ( --rep->ref <= 0 ) delete rep;
  265.     rep = y.rep; 
  266.   }
  267.   else {
  268.     unique();
  269.     copy(y.rep,rep);
  270.   }
  271.   return *this;
  272. }
  273.  
  274. inline Fix  Fix::operator = (double& d)
  275. {
  276.   int oldlen = rep->len;
  277.   if ( --rep->ref <= 0 ) delete rep;
  278.   rep = new_Fix(oldlen,d);
  279.   return *this;
  280. }
  281.  
  282. inline int operator == (Fix&  x, Fix&  y)
  283. {
  284.   return compare(x.rep, y.rep) == 0; 
  285. }
  286.  
  287. inline int operator != (Fix&  x, Fix&  y)
  288. {
  289.   return compare(x.rep, y.rep) != 0; 
  290. }
  291.  
  292. inline int operator <  (Fix&  x, Fix&  y)
  293. {
  294.   return compare(x.rep, y.rep) <  0; 
  295. }
  296.  
  297. inline int operator <= (Fix&  x, Fix&  y)
  298. {
  299.   return compare(x.rep, y.rep) <= 0; 
  300. }
  301.  
  302. inline int operator >  (Fix&  x, Fix&  y)
  303. {
  304.   return compare(x.rep, y.rep) >  0; 
  305. }
  306.  
  307. inline int operator >= (Fix&  x, Fix&  y)
  308. {
  309.   return compare(x.rep, y.rep) >= 0; 
  310. }
  311.  
  312. inline Fix& Fix::operator +  ()
  313. {
  314.   return *this;
  315. }
  316.  
  317. inline Fix Fix::operator -  ()
  318. {
  319.   _Fix r = negate(rep); return r;
  320. }
  321.  
  322. inline Fix      operator +  (Fix&  x, Fix& y)
  323. {
  324.   _Fix r = add(x.rep, y.rep); return r;
  325. }
  326.  
  327. inline Fix      operator -  (Fix&  x, Fix& y)
  328. {
  329.   _Fix r = subtract(x.rep, y.rep); return r;
  330. }
  331.  
  332. inline Fix      operator *  (Fix&  x, Fix& y)
  333. {
  334.   _Fix r = multiply(x.rep, y.rep); return r;
  335. }
  336.  
  337. inline Fix      operator *  (Fix&  x, int y)
  338. {
  339.   _Fix r = multiply(x.rep, y); return r;
  340. }
  341.  
  342. inline Fix      operator *  (int  y, Fix& x)
  343. {
  344.   _Fix r = multiply(x.rep, y); return r;
  345. }
  346.  
  347. inline Fix operator / (Fix& x, Fix& y)
  348. {
  349.   _Fix r = divide(x.rep, y.rep); return r;
  350. }
  351.  
  352. inline Fix  Fix::operator += (Fix& y)
  353. {
  354.   unique(); add(rep, y.rep, rep); return *this;
  355. }
  356.  
  357. inline Fix  Fix::operator -= (Fix& y)
  358. {
  359.   unique(); subtract(rep, y.rep, rep); return *this;
  360. }
  361.  
  362. inline Fix  Fix::operator *= (Fix& y)
  363. {
  364.   unique(); multiply(rep, y.rep, rep); return *this;
  365. }
  366.  
  367. inline Fix  Fix::operator *= (int y)
  368. {
  369.   unique(); multiply(rep, y, rep); return *this;
  370. }
  371.  
  372. inline Fix Fix::operator /= (Fix& y)
  373. {
  374.   unique(); divide(rep, y.rep, rep); return *this;
  375. }
  376.  
  377. inline Fix operator % (Fix& x, int y)
  378. {
  379.   Fix r((int )x.rep->len + y, x); return r;
  380. }
  381.  
  382. inline Fix      operator << (Fix&  x, int y)
  383. {
  384.   _Fix rep = shift(x.rep, y); return rep;
  385. }
  386.  
  387. inline Fix      operator >> (Fix&  x, int y)
  388. {  
  389.   _Fix rep = shift(x.rep, -y); return rep;
  390. }
  391.  
  392. inline Fix Fix::operator <<= (int y)
  393. {
  394.   unique(); shift(rep, y, rep); return *this;
  395. }
  396.  
  397. inline Fix  Fix::operator >>= (int y)
  398. {
  399.   unique(); shift(rep, -y, rep); return *this;
  400. }
  401.  
  402. #ifdef __GNUG__
  403. inline Fix operator <? (Fix& x, Fix& y)
  404. {
  405.   if ( compare(x.rep, y.rep) <= 0 ) return x; else return y;
  406. }
  407.  
  408. inline Fix operator >? (Fix& x, Fix& y)
  409. {
  410.   if ( compare(x.rep, y.rep) >= 0 ) return x; else return y;
  411. }
  412. #endif
  413.  
  414. inline Fix abs(Fix  x)
  415. {
  416.   _Fix r = (compare(x.rep) >= 0 ? new_Fix(x.rep->len,x.rep) : negate(x.rep));
  417.   return r;
  418. }
  419.  
  420. inline int sgn(Fix& x)
  421. {
  422.   int a = compare(x.rep);
  423.   return a == 0 ? 0 : (a > 0 ? 1 : -1);
  424. }
  425.  
  426. inline int length(Fix& x)
  427. {
  428.   return x.rep->len;
  429. }
  430.  
  431. inline ostream& operator << (ostream& s, Fix& y)
  432. {
  433.   return s << Ftoa(y);
  434. }
  435.  
  436. inline void    negate (Fix& x, Fix& r)
  437. {
  438.   negate(x.rep, r.rep);
  439. }
  440.  
  441. inline void    add (Fix& x, Fix& y, Fix& r)
  442. {
  443.   add(x.rep, y.rep, r.rep);
  444. }
  445.  
  446. inline void    subtract (Fix& x, Fix& y, Fix& r)
  447. {
  448.   subtract(x.rep, y.rep, r.rep);
  449. }
  450.  
  451. inline void    multiply (Fix& x, Fix& y, Fix& r)
  452. {
  453.   multiply(x.rep, y.rep, r.rep);
  454. }
  455.  
  456. inline void    divide (Fix& x, Fix& y, Fix& q, Fix& r)
  457. {
  458.   divide(x.rep, y.rep, q.rep, r.rep);
  459. }
  460.  
  461. inline void    shift (Fix& x, int y, Fix& r)
  462. {
  463.   shift(x.rep, y, r.rep);
  464. }
  465.  
  466. #endif
  467.